<template>
  <view class="s-dropdown-item" :class="custom_class" :style="custom_style">
    <s-popup
      v-model="visible"
      custom-class="s-dropdown-item__popup"
      :position="menuData.position"
      :z-index="menuData.zIndex"
      :custom-style="{ top, bottom }"
      :animate-duration="duration"
      :mask="menuData.mask"
      :mask-close="menuData.maskClose"
      :mask-opacity="menuData.maskOpacity"
      @open="onOpen"
      @opend="onOpend"
      @close="onClose"
      @closed="onClosed"
    >
      <slot>
        <view>
          <s-cell
            v-for="(item, index) of validOptions"
            :key="index"
            :title="item[labelKey]"
            :custom-class="{
              's-dropdown-item__option': true,
              's-dropdown-item__option--active': isActive(index),
            }"
            :custom-style="{
              color: isActive(index) ? menuData.activeColor : '',
            }"
            @click="onSelect(index)"
          >
            <template #right>
              <s-icon v-if="isActive(index)" name="success" />
            </template>
          </s-cell>
        </view>
      </slot>
    </s-popup>
  </view>
</template>

<script>
import componentMixin from '../../mixins/componentMixin';
import toValidListData from '../../utils/toValidListData';

/**
 * s-dropdown-item 下拉菜单子项
 * @description 向下弹出的菜单列表
 * @property {String|Number} sort 父级v-if动态显示隐藏，传入sort可使其正确排列顺序
 * @property {Number|String|Boolean} value
 * @property {Array} options 选项数组
 * @property {String} title 当前选中项文字
 * @property {String} labelKey 标签名称属性字段，默认 label
 * @property {String} valueKey 标签匹配属性字段，默认 value
 * @property {Function} beforeOpen (callback) 显示时拦截钩子可调用callback自动控制显示时机
 * @event {Function} change (value) 点击选项导致 value 变化时触发
 * @event {Function} open 打开弹出层时触发
 * @event {Function} opened 打开弹出层且动画结束后触发
 * @event {Function} close 关闭弹出层时触发
 * @event {Function} closed 关闭弹出层且动画结束后触发
 * @example <s-dropdown-item></s-dropdown-item>
 */
export default {
  name: 'SDropdownItem',
  mixins: [componentMixin],
  props: {
    sort: {
      type: [String, Number],
      default: 0,
    },
    value: {
      type: [Number, String, Boolean],
      default: '',
    },
    options: {
      type: Array,
      default: () => [],
    },
    title: {
      type: String,
      default: '',
    },
    disabled: Boolean,
    labelKey: {
      type: String,
      default: 'label',
    },
    valueKey: {
      type: String,
      default: 'value',
    },
    beforeOpen: Function,
  },
  data: () => ({
    visible: false,
    inVisible: false,
    top: '',
    bottom: '',
    noTransition: false,
  }),
  computed: {
    menuData() {
      return {
        activeColor: this.$sDropdownMenu.activeColor,
        duration: this.$sDropdownMenu.duration,
        position: this.$sDropdownMenu.direction === 'down' ? 'top' : 'bottom',
        zIndex: this.$sDropdownMenu.zIndex,
        mask: this.$sDropdownMenu.mask,
        maskClose: this.$sDropdownMenu.maskClose,
        maskOpacity: this.$sDropdownMenu.maskOpacity,
      };
    },
    validOptions() {
      return toValidListData(this.options, this.valueKey, this.labelKey);
    },
    duration() {
      return this.noTransition ? 0 : this.menuData.duration;
    },
  },
  created() {
    this.$sDropdownMenu = this.$getParentUntil('SDropdownMenu');
    this.$sDropdownMenu.list.push(this);
    this.$sDropdownMenu.list.sort((a, b) => a.sort == b.sort ? 0 : a.sort > b.sort ? 1 : -1);
  },
  beforeDestroy() {
    this.$sDropdownMenu.list = this.$sDropdownMenu.list.filter(item => item !== this);
  },
  methods: {
    isActive(index) {
      return this.validOptions[index][this.valueKey] === this.value;
    },
    toggle(visible, noTransition) {
      if (typeof visible !== 'boolean') {
        visible = !this.visible;
      }
      if (visible === this.visible) return;
      this.noTransition = !!noTransition;
      if (visible) {
        const beforeOpen = this.$getPropsFn('beforeOpen');
        if (beforeOpen) {
          beforeOpen(this.showPopup);
        } else {
          this.showPopup();
        }
      } else {
        this.visible = false;
      }
    },
    showPopup() {
      this.$sDropdownMenu.getRect().then(res => {
        this.top = '';
        this.bottom = '';
        if (this.$sDropdownMenu.direction === 'down') {
          this.top = (res.bottom + this.$sDropdownMenu.windowTop) + 'px';
        } else {
          this.bottom = (this.$sDropdownMenu.windowHeight - res.top) + 'px';
        }
        this.visible = true;
      });
    },
    onSelect(index) {
      const value = this.validOptions[index][this.valueKey];
      if (value !== this.value) {
        this.$emit('input', value);
        this.$emit('change', value);
      }
      this.toggle();
    },
    onOpen() {
      this.inVisible = true;
      this.$emit('open');
    },
    onOpend() {
      this.$emit('opend');
    },
    onClose() {
      this.$emit('close');
    },
    onClosed() {
      this.inVisible = false;
      this.$emit('closed');
    },
  },
};
</script>

<style lang="scss" src="./index.scss"></style>
